﻿#region Usings

using System;
using System.Collections.Generic;
using System.Linq;
using System.Xml.Linq;
using FeedReader.Data;
using FeedReader.Enums;

#endregion

namespace FeedReader.Xml
{
    public static class FeedRssXmlParser
    {
        private static string _cacheFolder;
        private static bool _useCache;

        public static bool TryParse(XDocument xmlFeed, ref Feed feed, string cacheFolder, bool downloadImages, List<FeedItemFilter> itemFilters)
        {
            _cacheFolder = cacheFolder;
            _useCache = true;
            return TryParse(xmlFeed, ref feed, downloadImages, itemFilters);
        }

        public static bool TryParse(XDocument xmlFeed, ref Feed feed, bool downloadImages, List<FeedItemFilter> itemFilters)
        {
            Feed rFeed = feed;
            XElement element = xmlFeed.Element("rss");
            if (element != null)
            {
                LogEvents.InvokeOnDebug(new FeedArgs("This is a RSS feed. Now parsing the xml data"));
                rFeed.ImagePath =
                    FeedXmlParser.ParseString(xmlFeed.Descendants("channel").Descendants("image").Elements("url"), "channel/image/url");
                rFeed.Title = Utils.Clean(FeedXmlParser.ParseString(xmlFeed.Descendants("channel").Elements("title"), "channel/title"));
                rFeed.Description =
                    Utils.Clean(FeedXmlParser.ParseString(xmlFeed.Descendants("channel").Elements("description"), "channel/description"));


                try
                {
                    FeedItem feedItem;
                    int i = 1;
                    foreach (XElement item in xmlFeed.Descendants("item"))
                    {
                        feedItem = new FeedItem();
                        feedItem.Author = Utils.Clean(FeedXmlParser.ParseString(item.Element("author"), "item[" + i + "]/author"));
                        feedItem.Title = Utils.Clean(FeedXmlParser.ParseString(item.Element("title"), "item/title"), true, false, true, true, itemFilters);
                        string enclosureType = FeedXmlParser.ParseString(item.Element("enclosure"), "type", "item/enclosure/attribute[type]");
                        LogEvents.InvokeOnDebug(new FeedArgs("Try to get feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] item image..."));
                        if (Utils.IsEnclosureTypeImage(enclosureType))
                        {
                            LogEvents.InvokeOnDebug(new FeedArgs("Enclosure of feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] item is an image. Parse image url..."));
                            feedItem.ImagePath = FeedXmlParser.ParseString(item.Element("enclosure"), "url", "item/enclosure/attribute[url]");
                        }
                        else
                        {
                            LogEvents.InvokeOnDebug(new FeedArgs("Enclosure of feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] item is not an image. It's " + enclosureType + ". Skipping parsing image url..."));
                            feedItem.ImagePath = string.Empty;
                        }
                        
                        feedItem.PublishDate = FeedXmlParser.ParseDateTime(item.Element("pubDate"), "item/pubDate");
                        feedItem.Url = FeedXmlParser.ParseString(item.Element("link"), "item/link").Trim();
                        string description = FeedXmlParser.ParseString(item.Element("description"), "item/description");
                        description = Utils.Clean(description, false, true, true, false, itemFilters);
                        
                        if (string.IsNullOrEmpty(feedItem.ImagePath))
                        {
                            LogEvents.InvokeOnDebug(new FeedArgs("Try to get feed[" + rFeed.Title + "][" + feedItem.Title + "][" + i + "] image out of description field..."));
                            feedItem.ImagePath = Utils.GetImageOutOfDescription(description);
                        }
                        feedItem.Description = Utils.Clean(description, false, true, false, true, itemFilters);

                        rFeed.Items.Add(feedItem);
                        i++;
                    }
                    /*rFeed.Items = (from item in xmlFeed.Descendants("item")
                                   select new FeedItem
                                              {
                                                  Author = FeedXmlParser.ParseString(item.Element("author"), "item/author", item.),
                                                  ImagePath =
                                                      FeedXmlParser.ParseString(item.Element("enclosure"), "url", "item/enclosure/attribute[url]"),
                                                  Title = Utils.Clean(FeedXmlParser.ParseString(item.Element("title"), "item/title")),
                                                  PublishDate = FeedXmlParser.ParseDateTime(item.Element("pubDate"), "item/pubDate"),
                                                  UrlPath = FeedXmlParser.ParseString(item.Element("link"), "item/link"),
                                                  Description =
                                                      Utils.Clean(FeedXmlParser.ParseString(item.Element("description"), "item/description")),
                                              }).OrderByDescending(feedItem => feedItem.PublishDate).ToList();*/
                    if (downloadImages)
                    {
                        LogEvents.InvokeOnInfo(new FeedArgs("Try to get feed images either from cache or from download links"));
                        feed = _useCache ? Utils.DownloadImages(rFeed, _cacheFolder) : Utils.DownloadImages(rFeed);
                    }
                    else feed = rFeed;
                    feed.Items = feed.Items.OrderByDescending(fItem => fItem.PublishDate).ToList();
                    LogEvents.InvokeOnDebug(new FeedArgs("Parsing of RSS feed done. See above for possibly errors or warnings"));
                    return true;
                }
                catch (Exception ex)
                {
                    LogEvents.InvokeOnError(new FeedArgs("Error parsing RSS feed", ex.Message, ex.StackTrace));
                    //feed = null;
                    return false;
                }
            }
            LogEvents.InvokeOnDebug(new FeedArgs("This is not an RSS feed or the downloaded xml file is not a valid feed"));
            //feed = null;
            return false;
        }
    }
}